package de.hsb.ai.agent.misterx;

import jade.core.AID;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import de.hsb.ai.agent.misterx.brain.Brain;
import de.hsb.ai.agent.misterx.brain.GraphAnalyser.DangerZone;
import de.hsb.ai.agent.misterx.brain.geoanalyser.GeoAnalyser;
import de.hsb.ai.agent.misterx.pathfinding.Node;
import game.IDraw;
import game.Move;


public class Drawer implements IDraw {

	private static boolean ENABLE = false;
	private GeoAnalyser _geoAnalyser = null;

	public final static int DRAW_1 = 0;
	public final static int CONVEX_HULL = 1;
	public final static int CONVEX_HULL_CENTROID = 2;
	public final static int CONVEX_HULL_AREA = 3;
	public final static int PLAYERMOTION = 4;
	public final static int CONNECTIONLINE = 5;
	public final static int CONVEX_HULL_DIRECTION = 6;
	public final static int WALKPATH = 7;
	public final static int COSTS = 8;
	public final static int DANGERZONES = 9;
	
	public static int MAXSHOWZONES = 10;
	
	private static boolean convexeHull, convexeHullCentroid, convexeHullArea, playerMotion, connectionLine, convexeHullDirection, walkingPath, heuristicCost, dangerZones;
	
	private static List<List<Node>> WALKINGPATH;
	private static List<List<Node>> HEURISTICS;
	private static List<List<DangerZone>> DANGERZONE;
	private static List<Boolean> VISIBLE;
	private static List<String> TECHNIC;
	
	public Drawer(GeoAnalyser geoAnalyser) {
		this._geoAnalyser = geoAnalyser;
		WALKINGPATH = new ArrayList<List<Node>>();
		HEURISTICS = new ArrayList<List<Node>>();
		DANGERZONE = new ArrayList<List<DangerZone>>();
		VISIBLE = new ArrayList<Boolean>();
		TECHNIC = new ArrayList<String>();
	}
	
	/**
	 * 
	 * @param c
	 */
	public static void switchFeature(int c) {
		if(c == CONVEX_HULL) convexeHull = !convexeHull;
		if(c == CONVEX_HULL_CENTROID) convexeHullCentroid = !convexeHullCentroid;
		if(c == CONVEX_HULL_AREA) convexeHullArea = !convexeHullArea;
		if(c == PLAYERMOTION) playerMotion = !playerMotion;
		if(c == CONNECTIONLINE) connectionLine = !connectionLine;
		if(c == CONVEX_HULL_DIRECTION) convexeHullDirection = !convexeHullDirection;
		if(c == WALKPATH) walkingPath = !walkingPath;
		if(c == COSTS) heuristicCost = !heuristicCost;
		if(c == DANGERZONES) dangerZones = !dangerZones;
	}
	
	/**
	 * 
	 * @param c
	 * @return
	 */
	public static boolean isFeatureON(int c) {
		if(c == CONVEX_HULL) return convexeHull;
		if(c == CONVEX_HULL_CENTROID) return convexeHullCentroid;
		if(c == CONVEX_HULL_AREA) return convexeHullArea;
		if(c == PLAYERMOTION) return playerMotion;
		if(c == CONNECTIONLINE) return connectionLine;
		if(c == CONVEX_HULL_DIRECTION) return convexeHullDirection;
		if(c == WALKPATH) return walkingPath;
		if(c == COSTS) return heuristicCost;
		if(c == DANGERZONES) return dangerZones;
		if(c == DRAW_1) return ENABLE;
		return false;
	}
	
	/**
	 * aktiviert das Einzeichnen der Elemente.
	 * @param enable
	 */
	public void activate(boolean enable) {
		ENABLE = enable;
	}

	/**
	 * fügt einen Graphenstrecke hinzu.
	 * @param _walkingPath
	 */
	public static void addPath(List<Node> walkingPath) {
		WALKINGPATH.add(walkingPath);
	}
	
	/**
	 * fügt eine Liste von Nodes hinzu.
	 * @param heuristics
	 */
	public static void addNodeHeuristics(List<Node> heuristics) {
		HEURISTICS.add(heuristics);
	}
	
	public static void addVisible(boolean visible) {
		VISIBLE.add(visible);
	}
	
	/**
	 * fügt eine List von Gefahrenzonen hinzu.
	 * @param dangeZones
	 */
	public static void addDangerZones(List<DangerZone> dangeZones) {
		DANGERZONE.add(dangeZones);
	}
	
	
	
	/**
	 * 
	 */
	@Override
	public void paint(Graphics g, int iteration) {
		if(ENABLE) {
			iteration += 0;
			
			Graphics2D g2 = (Graphics2D) g;
			Stroke stroke = new BasicStroke(2);
			g2.setStroke(stroke);

			//Konvexe Hülle zeichnen.
			if(convexeHull) {
			if(iteration+1 < this._geoAnalyser._polygons.size() && this._geoAnalyser._polygons.get(iteration+1) != null) {
				Move move = Brain.HISTORYCAPTURER.getHistory(Brain.getOwnAID()).getMove(iteration+1);
				if(move != null && this._geoAnalyser.isInPolygon(move.getNode(), this._geoAnalyser._polygons.get(iteration+1))) {
					g.setColor(Color.ORANGE);
				} else {
					g.setColor(Color.RED);
				}
				
				if(iteration+1 < this._geoAnalyser._polygons.size()) {
					g.drawPolygon(this._geoAnalyser._polygons.get(iteration+1));
				}
			}
			}
			
			if(convexeHullCentroid) {
			//Schwerpunkte zeichnen.
			if(iteration < this._geoAnalyser._points.size() && this._geoAnalyser._points.get(iteration) != null) {
				g.setColor(Color.RED);
				if(iteration+1 < this._geoAnalyser._points.size()) {
					Point2D point = this._geoAnalyser._points.get(iteration+1);
					g.drawRect((int)point.getX(), (int)point.getY(), 5, 5);
				}
			}
			}
			
			if(convexeHullArea) {
			//Prozentuale Fläche zeichnen.
			if(iteration < this._geoAnalyser._numbers.size() && this._geoAnalyser._numbers.get(iteration) != null) {
				g.setColor(Color.RED);
				if(iteration+1 < this._geoAnalyser._numbers.size()) {
					g.drawString(this._geoAnalyser._numbers.get(iteration+1) + "", 20, 20);
				}
			}
			}
			
			if(playerMotion) {
			//Bewegungsrichtung zeichnen.
			List<AID> enemys = Brain.getEnemyAIDs();
			for(AID aid : enemys) {
				if(iteration != 0) {
					Move lastMove = Brain.HISTORYCAPTURER.getHistory(aid).getMove(iteration +1);
					if(lastMove != null) {
						Point position = Brain.GEOANALYSER.getNodePosition(lastMove.getNode());
						Point2D direction = Brain.HISTORYCAPTURER.getHistory(aid).getMovingDirectionByIndex(iteration+1);
						if(direction != null) {
							g.setColor(Color.WHITE);
							g.drawLine((int)position.x, (int)position.y, (int)(position.x + direction.getX()),  (int)(position.y + direction.getY()));
						}
					}	
				}
			}
			}
			
			if(connectionLine) {
				List<AID> enemys = Brain.getEnemyAIDs();
				//Verbindungsslinie zeichnen. (Only 2 Players)
				if(enemys.size() == 2) {
					g.setColor(Color.RED);
					Move lastMove1 = Brain.HISTORYCAPTURER.getHistory(enemys.get(0)).getMove(iteration +1);
					Move lastMove2 = Brain.HISTORYCAPTURER.getHistory(enemys.get(1)).getMove(iteration +1);
					if(lastMove1 != null && lastMove2 != null) {
						Point position1 = Brain.GEOANALYSER.getNodePosition(lastMove1.getNode());
						Point position2 = Brain.GEOANALYSER.getNodePosition(lastMove2.getNode());
						
						g.drawLine((int)position1.getX(), (int)position1.getY(), (int)position2.getX(), (int)position2.getY());
						
						Point2D centerPoint = Brain.GEOANALYSER.calculateLineCenter(position1, position2);
						g.drawRect((int)centerPoint.getX(), (int)centerPoint.getY(), 5, 5);
					}
				
				}
				}
			
			if(convexeHullDirection) {
			//Orientierung zeichnen.
			if(iteration < this._geoAnalyser._orientation.size() && this._geoAnalyser._orientation.get(iteration) != null) {
				g.setColor(Color.ORANGE);
				if(iteration+1 < this._geoAnalyser._points.size()) {
					Point2D point = this._geoAnalyser._points.get(iteration+1);
					g.drawLine((int)point.getX(), (int)point.getY(), (int)(point.getX() + this._geoAnalyser._orientation.get(iteration+1).getX()), (int)(point.getY() + this._geoAnalyser._orientation.get(iteration+1).getY()));
				}
			}
			}
		
			if(walkingPath) {
			//Wakingpath zeichnen.
			if(iteration+1 < WALKINGPATH.size()) {
				g.setColor(Color.YELLOW);
				List<Node> walk = WALKINGPATH.get(iteration+1);
				if(walk != null) {
					for(int i = 1; i < walk.size(); i++) {
						Point2D position1 = this._geoAnalyser.getNodePosition(walk.get(i)._index);
						Point2D position2 = this._geoAnalyser.getNodePosition(walk.get(i-1)._index);
							
						g.drawRect((int)position1.getX(), (int)position1.getY(), 10, 10);
						g.drawLine((int)position1.getX(), (int)position1.getY(), (int)position2.getX(), (int)position2.getY());
					}
				}
			}
			}
			
			if(heuristicCost) {
			//Heuristiken zeichnen.
			if(iteration+1 < HEURISTICS.size()) {
				g.setColor(Color.WHITE);
				List<Node> node = HEURISTICS.get(iteration+1);
				if(node != null) {
					for(int i = 1; i < node.size(); i++) {
						Point2D position = this._geoAnalyser.getNodePosition(node.get(i)._index);

						int costs = node.get(i)._H;
						g.drawRect((int)position.getX() - 20/2, (int)position.getY() - 20/2, 20, 20);
						g.drawString(costs + "", (int)position.getX() - 20/2, (int)position.getY() - (20/2) + 30);
					}
				}
			}
			}
			
			if(dangerZones) {
			List<AID> enemys = Brain.getEnemyAIDs();
				
			if(iteration+1 < DANGERZONE.size()) {
				g.setColor(Color.YELLOW);
				List<DangerZone> dangerZones = DANGERZONE.get(iteration+1);
				if(dangerZones != null) {
					for(int i = 1; i < dangerZones.size(); i++) {
						DangerZone dangerZone = dangerZones.get(i);
						Point2D position = this._geoAnalyser.getNodePosition(dangerZone._move.getNode());
						
						int radius = dangerZone._radius;
						if(radius <= MAXSHOWZONES) {
							//prüft welche AID und positioniert den String anders anhand dessen.
							int positionX = (int)position.getX() - 20/2;
							int positionY = (int)position.getY() - 20/2;
							//Multi
							for(int j = 0; j < enemys.size(); j++) {
								if(enemys.get(j).equals(dangerZone._aid)) {
									
									positionX += j*10;
									break;
								}
							}
							//
							g.drawString(radius + "", positionX, positionY);
							
						
						}
					}
				}
			}
			}
			
			if(iteration+1 < VISIBLE.size()) {
				if(VISIBLE.get(iteration+1)) {
					g.setColor(Color.RED);
					g.drawString("YOU ARE VISIBLE", 20, 30);
				}
			}
			
			if(iteration+1 < TECHNIC.size()) {
				g.setColor(Color.RED);
				g.drawString(TECHNIC.get(iteration+1), 20, 45);
			}
			
		}
	}

	/**
	 * 
	 * @param string
	 */
	public static void addMessage(String string) {
		TECHNIC.add(string);
	}

	

}
